﻿Imports System
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms

Namespace System.Workflow.ComponentModel.Design
    Friend MustInherit Class ScrollableItemStrip
        ' Events
        Public Custom Event SelectionChanged As SelectionChangeEventHandler([Of] SelectionChangeEventArgs)
            AddHandler(ByVal value As SelectionChangeEventHandler([Of] SelectionChangeEventArgs))
                AddHandler Me.itemStrip.SelectionChanged, value
            End AddHandler
            RemoveHandler(ByVal value As SelectionChangeEventHandler([Of] SelectionChangeEventArgs))
                RemoveHandler Me.itemStrip.SelectionChanged, value
            End RemoveHandler
        End Event

        ' Methods
        Public Sub New(ByVal serviceProvider As IServiceProvider, ByVal orientation As Orientation, ByVal itemSize As Size, ByVal margin As Size)
            If (serviceProvider Is Nothing) Then
                Throw New ArgumentNullException("serviceProvider")
            End If
            Me.serviceProvider = serviceProvider
            Me.orientation = orientation
            Me.margin = margin
            If (orientation = Orientation.Horizontal) Then
                Me.buttonSize = New Size(((itemSize.Width * 2) / 3), itemSize.Height)
            Else
                Me.buttonSize = New Size(itemSize.Width, ((itemSize.Height * 2) / 3))
            End If
            Me.itemStrip = Me.CreateItemStrip(serviceProvider, orientation, itemSize, margin)
            AddHandler Me.itemStrip.ScrollPositionChanged, New EventHandler(AddressOf Me.OnScrollPositionChanged)
        End Sub

        Protected MustOverride Function CreateItemStrip(ByVal serviceProvider As IServiceProvider, ByVal orientation As Orientation, ByVal itemSize As Size, ByVal margin As Size) As ItemStrip

        Public MustOverride Sub Draw(ByVal graphics As Graphics)

        Protected Function GetButtonBounds(ByVal scrollButton As ScrollButton) As Rectangle
            Dim empty As Rectangle = Rectangle.Empty
            empty.Size = Me.buttonSize
            If ((scrollButton = ScrollButton.Left) OrElse (scrollButton = ScrollButton.Up)) Then
                empty.X = (Me.bounds.X + Me.margin.Width)
                empty.Y = (Me.bounds.Y + Me.margin.Height)
                Return empty
            End If
            If ((scrollButton = ScrollButton.Right) OrElse (scrollButton = ScrollButton.Down)) Then
                If (Me.orientation = Orientation.Horizontal) Then
                    empty.X = (((Me.bounds.X + Me.margin.Width) + empty.Size.Width) + Me.itemStrip.Size.Width)
                    If (empty.X >= Me.bounds.Right) Then
                        empty.X = (Me.bounds.Right - empty.Size.Width)
                    End If
                    empty.Y = (Me.bounds.Y + Me.margin.Height)
                    Return empty
                End If
                empty.X = (Me.bounds.X + Me.margin.Width)
                empty.Y = (((Me.bounds.Y + Me.margin.Height) + empty.Size.Height) + Me.itemStrip.Size.Height)
                If (empty.Y >= Me.bounds.Bottom) Then
                    empty.Y = (Me.bounds.Bottom - empty.Size.Height)
                End If
            End If
            Return empty
        End Function

        Protected Function HitTest(ByVal mousePoint As Point) As ScrollButton
            If (Me.itemStrip.ScrollPosition > 0) Then
                Dim scrollButton As ScrollButton = If((Me.orientation = Orientation.Horizontal), ScrollButton.Left, ScrollButton.Up)
                If Me.GetButtonBounds(scrollButton).Contains(mousePoint) Then
                    Return scrollButton
                End If
            End If
            If ((Me.itemStrip.ScrollPosition + Me.itemStrip.MaxVisibleItems) < Me.itemStrip.Items.Count) Then
                Dim button2 As ScrollButton = If((Me.orientation = Orientation.Horizontal), ScrollButton.Right, ScrollButton.Down)
                If Me.GetButtonBounds(button2).Contains(mousePoint) Then
                    Return button2
                End If
            End If
            Return ScrollButton.Up
        End Function

        Protected Sub Invalidate()
            Dim service As WorkflowView = [TryCast](Me.serviceProvider.GetService(GetType(WorkflowView)),WorkflowView)
            If (Not service Is Nothing) Then
                service.InvalidateLogicalRectangle(Me.bounds)
            End If
        End Sub

        Public Overridable Sub OnMouseDown(ByVal e As MouseEventArgs)
            Dim pt As New Point(e.X, e.Y)
            If Me.itemStrip.Bounds.Contains(pt) Then
                Me.itemStrip.OnMouseDown(e)
            Else
                Dim button As ScrollButton = Me.HitTest(pt)
                If (button <> ScrollButton.Up) Then
                    Dim num As Integer = If(((button = ScrollButton.Left) OrElse (button = ScrollButton.Up)), -1, 1)
                    Me.itemStrip.ScrollPosition = (Me.itemStrip.ScrollPosition + num)
                End If
                If (e.Button = MouseButtons.Left) Then
                    Me.ActiveButton = button
                End If
            End If
        End Sub

        Public Overridable Sub OnMouseDragBegin(ByVal initialDragPoint As Point, ByVal e As MouseEventArgs)
        End Sub

        Public Overridable Sub OnMouseDragEnd()
        End Sub

        Public Overridable Sub OnMouseDragMove(ByVal e As MouseEventArgs)
        End Sub

        Public Overridable Sub OnMouseEnter(ByVal e As MouseEventArgs)
            Me.itemStrip.OnMouseEnter(e)
        End Sub

        Public Overridable Sub OnMouseLeave()
            Me.itemStrip.OnMouseLeave
            Me.ActiveButton = ScrollButton.Up
        End Sub

        Public Overridable Sub OnMouseMove(ByVal e As MouseEventArgs)
            Me.itemStrip.OnMouseMove(e)
            If (e.Button = MouseButtons.Left) Then
                Me.ActiveButton = Me.HitTest(New Point(e.X, e.Y))
            End If
        End Sub

        Public Overridable Sub OnMouseUp(ByVal e As MouseEventArgs)
            Dim pt As New Point(e.X, e.Y)
            If Me.itemStrip.Bounds.Contains(pt) Then
                Me.itemStrip.OnMouseUp(e)
            End If
            Me.ActiveButton = ScrollButton.Up
        End Sub

        Private Sub OnScrollPositionChanged(ByVal sender As Object, ByVal e As EventArgs)
            Me.Invalidate
        End Sub


        ' Properties
        Property ActiveButton As ScrollButton
            Protected Get
                Return Me.activeButton
            End Get
            Private Set(ByVal value As ScrollButton)
                If (Me.activeButton <> value) Then
                    Me.activeButton = value
                    Me.Invalidate
                End If
            End Set
        End Property

        Public ReadOnly Property Bounds As Rectangle
            Get
                Return Me.bounds
            End Get
        End Property

        Public ReadOnly Property Items As IList([Of] ItemInfo)
            Get
                Return Me.itemStrip.Items
            End Get
        End Property

        Public Property Location As Point
            Get
                Return Me.bounds.Location
            End Get
            Set(ByVal value As Point)
                If (Me.bounds.Location <> value) Then
                    Me.Invalidate
                    Me.bounds.Location = value
                    Dim buttonBounds As Rectangle = Me.GetButtonBounds(ScrollButton.Left)
                    If (Me.orientation = Orientation.Horizontal) Then
                        Me.itemStrip.Location = New Point(buttonBounds.Right, buttonBounds.Top)
                    Else
                        Me.itemStrip.Location = New Point(buttonBounds.Left, buttonBounds.Bottom)
                    End If
                    Me.Invalidate
                End If
            End Set
        End Property

        Public ReadOnly Property Orientation As Orientation
            Get
                Return Me.orientation
            End Get
        End Property

        Public Property SelectedItem As ItemInfo
            Get
                Return Me.itemStrip.SelectedItem
            End Get
            Set(ByVal value As ItemInfo)
                Me.itemStrip.SelectedItem = value
            End Set
        End Property

        Public Property Size As Size
            Get
                Return Me.bounds.Size
            End Get
            Set(ByVal value As Size)
                If (Me.bounds.Size <> value) Then
                    Me.Invalidate
                    Me.bounds.Size = value
                    Dim requiredSize As Size = Me.itemStrip.RequiredSize
                    Dim num As Integer = 0
                    If (Me.orientation = Orientation.Horizontal) Then
                        num = (Me.bounds.Width - (2 * ((2 * Me.margin.Width) + Me.buttonSize.Width)))
                        num = (num - Me.margin.Width)
                        If ((Me.margin.Width + Me.itemStrip.ItemSize.Width) > 0) Then
                            num = (num - (num Mod (Me.margin.Width + Me.itemStrip.ItemSize.Width)))
                        End If
                        Me.itemStrip.Size = New Size(Math.Min(num, requiredSize.Width), Math.Min(Me.bounds.Height, requiredSize.Height))
                    Else
                        num = (Me.bounds.Height - (2 * ((2 * Me.margin.Height) + Me.buttonSize.Height)))
                        num = (num - Me.margin.Height)
                        If ((Me.margin.Height + Me.itemStrip.ItemSize.Height) > 0) Then
                            num = (num - (num Mod (Me.margin.Height + Me.itemStrip.ItemSize.Height)))
                        End If
                        Me.itemStrip.Size = New Size(Math.Min(Me.bounds.Width, requiredSize.Width), Math.Min(num, requiredSize.Height))
                    End If
                    Me.Invalidate
                End If
            End Set
        End Property


        ' Fields
        Private activeButton As ScrollButton
        Private bounds As Rectangle = Rectangle.Empty
        Private buttonSize As Size
        Protected itemStrip As ItemStrip
        Private margin As Size
        Private orientation As Orientation
        Protected serviceProvider As IServiceProvider
    End Class
End Namespace

